package com.piece.core.db.util;

import com.piece.core.db.context.DynamicDataSource;
import com.piece.core.db.context.DynamicDataSourceContextHolder;
import com.piece.core.framework.constant.FrameWorkConstants;
import com.piece.core.framework.util.object.BeanUtil;
import com.piece.core.framework.util.basic.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import javax.sql.DataSource;
import java.sql.ResultSet;
import java.util.List;
import java.util.Map;

/**
 * 数据源操作工具类
 */
@Slf4j
public class DataBaseUtil {

    public static JdbcTemplate jdbcTemplate() {
        return (JdbcTemplate) SpringUtil.getBean("jdbcTemplate");
    }

    /**
     * 加载数据源
     *
     * @param sources 数据源参数(dbKey、driverClassName、url、username、password)
     */
    public static void createDataSource(List<Map> sources) {
        // 遍历从数据源
        for (int i = 0; i < sources.size(); i++) {
            createDataSource(sources.get(i));
        }
    }

    /**
     * 创建数据源
     *
     * @param dbInfo 数据源参数(dbKey、driverClassName、url、username、password)
     */
    public static boolean createDataSource(Map dbInfo) {
        DynamicDataSource dynamicDataSource = (DynamicDataSource) SpringUtil.getBean("dynamicDataSource");
        return dynamicDataSource.createDataSource((String) dbInfo.get("dbKey"), (String) dbInfo.get("driverClassName"), (String) dbInfo.get("url"), (String) dbInfo.get("username"), (String) dbInfo.get("password"));
    }

    /**
     * 删除数据源
     *
     * @param key 数据源key
     */
    public static boolean deleteDataSource(String key) {
        DynamicDataSource dynamicDataSource = (DynamicDataSource) SpringUtil.getBean("dynamicDataSource");
        return dynamicDataSource.delDataSource(key);
    }

    /**
     * 更新数据
     *
     * @param key    数据源key
     * @param sql    执行sql
     * @param params 参数
     */
    public static boolean update(String key, String sql, List<Object> params) {
        try {
            changeDataSource(key);
            jdbcTemplate().update(sql, params.toArray());
        } catch (Exception e) {
            log.error("更新SQL异常：{}", e.getMessage());
            return false;
        } finally {
            clearDataSource();
        }
        return true;
    }

    /**
     * 批量更新数据
     *
     * @param key    数据源key
     * @param sql    执行sql
     * @param params 参数
     */
    public static boolean batchUpdate(String key, String sql, List<Object[]> params) {
        try {
            changeDataSource(key);
            jdbcTemplate().batchUpdate(sql, params);
        } catch (Exception e) {
            log.error("更新SQL异常：{}", e.getMessage());
            return false;
        } finally {
            clearDataSource();
        }
        return true;
    }

    /**
     * 批量更新数据
     *
     * @param key 数据源key
     * @param sql 执行sql数组
     * @return
     */
    public static boolean batchUpdate(String key, String... sql) {
        try {
            changeDataSource(key);
            jdbcTemplate().batchUpdate(sql);
        } catch (Exception e) {
            log.error("更新SQL异常：{}", e.getMessage());
            return false;
        } finally {
            clearDataSource();
        }
        return true;
    }

    /**
     * 执行sql
     *
     * @param key 数据源key
     * @param sql 执行sql
     * @return
     */
    public static boolean execute(String key, String sql) {
        try {
            changeDataSource(key);
            jdbcTemplate().execute(sql);
        } catch (Exception e) {
            log.error("执行SQL异常：{}", e.getMessage());
            return false;
        } finally {
            clearDataSource();
        }
        return true;
    }

    /**
     * 查询对象
     *
     * @param key    数据源key
     * @param sql    执行sql
     * @param params 参数
     * @param clazz  返回结果类
     */
    public static <T> T queryForObject(String key, String sql, Object[] params, Class<T> clazz) {
        try {
            changeDataSource(key);
            return jdbcTemplate().query(sql, rs -> {
                return convert(rs, clazz);
            }, params);
        } catch (Exception e) {
            log.error("查询SQL异常：{}", e.getMessage());
        } finally {
            clearDataSource();
        }
        return null;
    }

    /**
     * 查询列表对象
     *
     * @param key    数据源key
     * @param sql    执行sql
     * @param params 参数
     * @param clazz  返回结果类
     */
    public static <T> List<T> queryForList(String key, String sql, Object[] params, Class<T> clazz) {
        try {
            changeDataSource(key);
            return jdbcTemplate().query(sql, (rs, rowNum) -> convert(rs, clazz), params);
        } catch (Exception e) {
            log.error("查询SQL异常：{}", e.getMessage());
            return null;
        } finally {
            clearDataSource();
        }
    }

    /**
     * 查询列表对象
     *
     * @param key    数据源key
     * @param sql    执行sql
     * @param params 参数
     */
    public static <T> List<T> queryForList(String key, String sql, Object[] params, RowMapper<T> rowMapper) {
        try {
            changeDataSource(key);
            return jdbcTemplate().query(sql, rowMapper, params);
        } catch (Exception e) {
            log.error("查询SQL异常：{}", e.getMessage());
            return null;
        } finally {
            clearDataSource();
        }
    }

    private static <T> T convert(ResultSet rs, Class<T> clazz) {
        T bean = null;
        try {
            bean = clazz.newInstance();
            BeanUtil.resultSetToBean(rs, bean);
        } catch (Exception e) {
            log.error("查询SQL转换对象异常：{}", e.getMessage());
        } finally {
            return bean;
        }
    }

    /**
     * 查询Map
     *
     * @param key    数据源key
     * @param sql    执行sql
     * @param params 参数
     * @return
     */
    public static Map<String, Object> queryForMap(String key, String sql, Object[] params) {
        try {
            changeDataSource(key);
            if (params == null) {
                return jdbcTemplate().queryForMap(sql);
            }
            return jdbcTemplate().queryForMap(sql, params);
        } catch (Exception e) {
            log.error("查询SQL异常：{}", e.getMessage());
        } finally {
            clearDataSource();
        }
        return null;
    }

    /**
     * 查询Map列表
     *
     * @param key    数据源key
     * @param sql    执行sql
     * @param params 参数
     * @return
     */
    public static List<Map<String, Object>> queryForList(String key, String sql, Object[] params) {
        try {
            changeDataSource(key);
            if (null == params) {
                return jdbcTemplate().queryForList(sql);
            }
            return jdbcTemplate().queryForList(sql, params);
        } catch (Exception e) {
            log.error("查询SQL异常：{}", e.getMessage());
        } finally {
            clearDataSource();
        }
        return null;
    }

    public static void changeDataSource(String key) {
        if (!FrameWorkConstants.DATASOURCE_MASTER.equals(key)) {
            DynamicDataSourceContextHolder.setDateSourceType(key);
        }
    }

    public static void clearDataSource() {
        DynamicDataSourceContextHolder.clearDateSourceType();
    }

    public static DataSource getDataSource() {
        return DynamicDataSourceContextHolder.getCurrentDataSource();
    }
}
